﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using FlexiCommerce.Configuration;
using System.IO;
using FlexiCommerce.Components;
using System.Drawing.Imaging;

namespace FlexiCommerce.Web.Handlers
{
    public class ImageHandler : IHttpHandler
    {

        #region IHttpHandler Members

        public bool IsReusable
        {
            get { return false; }
        }
        public void ProcessRequest(HttpContext context)
        {
            TryToFindImageFirst(context);

            Image image = Find.Images.Where(i => i.ID == ImageId(context)).SingleOrDefault();

            if (image == null)
            {
                context.Response.End();
            }

            DirectoryInfo imageDirectory = new DirectoryInfo(EnsureFoldersExists(image));
            if (GetWidthAndWidth(context).Count == 0)
            {
                image.Bitmap.Save(imageDirectory.FullName + ImageId(context).ToString() + GetExtension(image.Bitmap), GetImageFormat(image.Bitmap));
                WriteFileToResponse(imageDirectory.GetFiles(ImageId(context).ToString() + GetExtension(image.Bitmap))[0], context);
                context.Response.End();
            }
            else
            {
                ImageUtility.ResizeAndSave(image.Bitmap,
                                           GetWidthAndWidth(context)["Width"].ToString() + "x" +
                                           GetWidthAndWidth(context)["Height"].ToString() + GetExtension(image.Bitmap),
                                           imageDirectory.FullName, GetImageFormat(image.Bitmap), GetWidthAndWidth(context)["Width"],
                                           GetWidthAndWidth(context)["Height"]);
                WriteFileToResponse(imageDirectory.GetFiles(GetWidthAndWidth(context)["Width"].ToString() + "x" +
                                                            GetWidthAndWidth(context)["Height"].ToString() + ".*")[0],
                                    context);
                context.Response.End();
            }


        }
        private string EnsureFoldersExists(Image image)
        {
            string imagesDirectory =
               HttpContext.Current.Server.MapPath(
                   FlexiCommerce.Context.Current.Resolve<HostSection>().ImageCacheFolder);
            string imageDirectory = imagesDirectory + "/" + image.ID.ToString() + "/";

            if (!System.IO.Directory.Exists(imagesDirectory))
                Directory.CreateDirectory(imagesDirectory);

            if (!Directory.Exists(imageDirectory))
                Directory.CreateDirectory(imageDirectory);

            return imageDirectory;
        }
        private void WriteFileToResponse(FileInfo file, HttpContext context)
        {
            context.Response.StatusCode = 200;
            context.Response.WriteFile(file.FullName);
            context.Response.ContentType = GetContentType(file.FullName);
        }
        private void TryToFindImageFirst(HttpContext context)
        {
            string imagesDirectory =
                HttpContext.Current.Server.MapPath(
                    FlexiCommerce.Context.Current.Resolve<HostSection>().ImageCacheFolder);
            string imageDirectory = imagesDirectory + ImageId(context).ToString();
            if (Directory.Exists(imageDirectory))
            {
                DirectoryInfo imaged = new DirectoryInfo(imageDirectory);
                FileInfo[] results = null;
                if (GetWidthAndWidth(context).Count == 0)
                {
                    results = imaged.GetFiles(ImageId(context).ToString() + ".*");
                }
                else
                {
                    results =
                        imaged.GetFiles(GetWidthAndWidth(context)["Width"] + "x" + GetWidthAndWidth(context)["Height"] +
                                        ".*");
                }
                if (results.Length > 0)
                {
                    WriteFileToResponse(results[0], context);
                    context.Response.End();
                }
            }
        }

        private IDictionary<string, int> widthAndHeight = null;
        private IDictionary<string, int> GetWidthAndWidth(HttpContext context)
        {
            if (widthAndHeight == null)
            {
                int width = 0;
                int height = 0;
                Components.Configuration config = Context.Persister.GetConfiguration();
                if (!string.IsNullOrEmpty(context.Request["height"]) && !string.IsNullOrEmpty(context.Request["width"]))
                {
                    int.TryParse(context.Request["height"], out height);
                    int.TryParse(context.Request["width"], out width);
                }
                switch (context.Request["size"])
                {
                    case "thumbnail":
                        width = config.Store.ThumbnailWidth;
                        height = config.Store.ThumbnailHeight;
                        break;
                    case "tiny":
                        width = config.Store.TinyWidth;
                        height = config.Store.TinyHeight;
                        break;
                }

                widthAndHeight = new Dictionary<string, int>();
                if (width != 0 && height != 0)
                {
                    widthAndHeight.Add("Width", width);
                    widthAndHeight.Add("Height", height);
                }
            }
            return widthAndHeight;

        }
        private int ImageId(HttpContext context)
        {
            if (string.IsNullOrEmpty(context.Request["id"]))
            {
                throw new FlexiException("You must specify and ID");
            }
            return int.Parse(context.Request["id"]);
        }
        string GetContentType(string path)
        {
            switch (Path.GetExtension(path))
            {
                case ".bmp": return "Image/bmp";
                case ".gif": return "Image/gif";
                case ".jpg": return "Image/jpeg";
                case ".png": return "Image/png";
                default: break;
            }
            return "";
        }
        private string GetExtension(System.Drawing.Image image)
        {
            if (image.RawFormat.Equals(ImageFormat.Bmp))
                return ".bmp";
            if (image.RawFormat.Equals(ImageFormat.Gif))
                return ".gif";
            if (image.RawFormat.Equals(ImageFormat.Png))
                return ".png";
            if (image.RawFormat.Equals(ImageFormat.Jpeg))
                return ".jpg";
            throw new FlexiException("Unsupported file format {0}", image.RawFormat.ToString());
        }
        private ImageFormat GetImageFormat(System.Drawing.Image image)
        {
            if (image.RawFormat.Equals(ImageFormat.Bmp))
                return ImageFormat.Bmp;
            if (image.RawFormat.Equals(ImageFormat.Gif))
                return ImageFormat.Gif;
            if (image.RawFormat.Equals(ImageFormat.Png))
                return ImageFormat.Png;
            if (image.RawFormat.Equals(ImageFormat.Jpeg))
                return ImageFormat.Jpeg;
            throw new FlexiException("Unsupported file format {0}", image.RawFormat.ToString());
        }
        #endregion
    }
}
